package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.apis.article.IArticleClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constans.WemediaConstants;
import com.heima.common.exception.CostumExcepition;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.*;
import com.heima.service.FileStorageService;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private GreenImageScan greenImageScan;
    @Qualifier("com.heima.apis.article.IArticleClient")
    @Autowired
    private IArticleClient articleClient ;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Override
    @Async
    @GlobalTransactional
    public void autoScanWmNews(Integer id) throws Exception {

        //根据id查询文章
        WmNews wmNews = wmNewsMapper.selectById(id);

        if(wmNews==null){
            throw new CostumExcepition(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断status是否为1
//        wmNews.getStatus()
        if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){

            //提取文字和图片放入map集合
            Map<String,Object> map=parseImageAndText(wmNews);

            //自定义敏感词过滤
            boolean isSensitive = handleSensitiveScan((String) map.get("text"), wmNews);
            if(!isSensitive) return;

            //审核文字
            boolean textScan=handleTextScan((String) map.get("text"),wmNews);
            if (!textScan){
                return;
            }

            //审核图片
            boolean imageScan=handleImageScan((List<String>)map.get("image"),wmNews);
            if(!imageScan){
                return;
            }

            //审核通过发布文章
            ResponseResult responseResult = saveAppArticle(wmNews);

            if(responseResult.getCode()!=200){
                throw  new CostumExcepition(AppHttpCodeEnum.SERVER_ERROR);
            }

            int a = 1/0;
            wmNews.setArticleId((Long) responseResult.getData());
            updateResult((short)9,wmNews,"审核通过");
        }



    }

    //自定义敏感词过滤
    private boolean handleSensitiveScan(String text, WmNews wmNews) {
        boolean flag = true;

        //获取所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(text);
        if(map.size() >0){
            updateResult((short) 2,wmNews,"当前文章中存在违规内容"+map);
            flag = false;
        }

        return flag;
    }

    //保存文章
    private ResponseResult saveAppArticle(WmNews wmNews) {

        ArticleDto dto = new ArticleDto();
        //属性的拷贝
        BeanUtils.copyProperties(wmNews,dto);
        //文章的布局
        dto.setLayout((int)wmNews.getType());
        //频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel != null){
            dto.setChannelName(wmChannel.getName());
        }

        //作者
        dto.setAuthorId((int) wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser != null){
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        if(wmNews.getArticleId() != null){
            dto.setId(wmNews.getArticleId());
        }
        dto.setCreatedTime(new Date());

        ResponseResult responseResult = articleClient.saveArticle(dto);

        return responseResult;
    }

    //图片审核
    private boolean handleImageScan(List<String> iamge, WmNews wmNews) throws Exception {
        boolean flag = true;

        if(iamge!=null&&iamge.size()!=0){

            //下载图片,放入集合
            List<byte[]> list=new ArrayList<>();

            for (String url:iamge){
                byte[] bytes = fileStorageService.downLoadFile(url);

                //从byte[]转换为butteredImage
                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
                BufferedImage imageFile = ImageIO.read(in);
                Tess4jClient client = new Tess4jClient();
                String text = client.doOCR(imageFile);

                boolean isSensitive = handleSensitiveScan(text, wmNews);
                if(!isSensitive){
                    return isSensitive;
                }

                list.add(bytes);
            }
            //审核图片
            //审核图片
            try {
                Map map = greenImageScan.imageScan(list);
                flag = isFlag(wmNews, flag, map);
            } catch (Exception e) {
                flag = false;
                e.printStackTrace();
            }

            Map map = greenImageScan.imageScan(list);

        }

        return flag;
    }

    //审核结果解析
    private boolean isFlag(WmNews wmNews, boolean flag, Map map) {
        if (map != null) {
            if (map.get("suggestion").equals("block")) {
                flag = false;
                updateResult((short) 2, wmNews, "文章含有违规内容");
            }

            if (map.get("suggestion").equals("review")) {
                flag = false;
                updateResult((short) 3, wmNews, "文章含有不确定内容");
            }
        }
        return flag;
    }

    //文字审核
    private boolean handleTextScan(String text,WmNews nwes) throws Exception {

       boolean flag=true;

        Map map = greenTextScan.greeTextScan(text);

        flag = isFlag(nwes, flag, map);
        return flag;
    }

    //保存审核结果
    private void updateResult(short status, WmNews nwes, String reason) {
        nwes.setStatus(status);
        nwes.setReason(reason);
        wmNewsMapper.updateById(nwes);
    }

    //提取news中的文字及图片
    private Map<String, Object> parseImageAndText(WmNews wmNews) {
        List<String> images=new ArrayList<>();
        StringBuffer text = new StringBuffer();

        String content = wmNews.getContent();

        if(StringUtils.isNotEmpty(content)){
            List<Map> maps= JSON.parseArray(content,Map.class);
            for (Map map : maps) {
                if(map.get("type").equals("text")){
                    text.append(map.get("value"));
                }else if(map.get("type").equals("image")) {
                    images.add((String) map.get("value"));
                }
            }
        }

        //标题中的文字
        text.append(wmNews.getTitle());

        //封面中的图片
        if(wmNews.getImages()!=null){
            images.addAll(Arrays.asList(wmNews.getImages().split(",")));
            images=images.stream().distinct().collect(Collectors.toList());
        }

        Map<String, Object> map = new HashMap<>();
        map.put("text",text.toString());
        map.put("image",images);
        return map;
    }
}
